package cz.acies.uniql.metadata;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Element;
import org.dom4j.dom.DOMElement;


import cz.acies.uniql.dialect.Dialect;
import cz.acies.uniql.utils.StringHelper;

public class IndexMetaData extends MetaData implements RelationalModel, Serializable
{
	private static final long serialVersionUID = 4568553927117126031L;
	
	private TableMetaData tbmd;
	private List<FieldMetaData> columns = new ArrayList<FieldMetaData>();
	private String type;
	private boolean unique;

	
	/* (non-Javadoc)
	 * @see com.smart4web.db.structure.RelationalModel#sqlCreateString()
	 */
	public String sqlCreateString() {
		return buildSqlCreateIndexString(
			getDialect(), getName(), getTableMetaData(), getColumnIterator(), false, dbmd().getCatalog(), dbmd().getSchema()
		);
	}

	/* (non-Javadoc)
	 * @see com.smart4web.db.structure.RelationalModel#sqlCreateString(cz.acies.uniql.dialect.Dialect, com.smart4web.db.structure.DBMetaData)
	 */
	public String sqlCreateString(Dialect dialect, DBMetaData dbmd) {
		return buildSqlCreateIndexString(
			dialect, getName(), getTableMetaData(), getColumnIterator(), false, dbmd.getCatalog(), dbmd.getSchema()
		);
	}

	public static String buildSqlCreateIndexString(Dialect dialect, String name, TableMetaData tbmd, Iterator<FieldMetaData> columns, boolean unique, String defaultCatalog, String defaultSchema) {
		StringBuffer buf = new StringBuffer("CREATE")
		.append(unique ? " UNIQUE" : "")
		.append(" INDEX ")
		.append(dialect.qualifyIndexName() ? name : StringHelper.unqualify(name))
		.append(" ON ").append(tbmd.getQualifiedName(dialect, defaultCatalog, defaultSchema))
		.append(" (");
		Iterator<FieldMetaData> iter = columns;
		while (iter.hasNext()) {
			buf.append(((FieldMetaData)iter.next()).getQuotedName(dialect));
			if (iter.hasNext())
				buf.append(", ");
		}
		buf.append(")");
		return buf.toString();
	}

	/* (non-Javadoc)
	 * @see com.smart4web.db.structure.RelationalModel#sqlDropString()
	 */
	public String sqlDropString() {
		return null;
	}

	public String sqlDropString(Dialect dialect, DBMetaData dbmd) {		
		return "DROP INDEX " + StringHelper.qualify(tbmd.getQualifiedName(dialect, dbmd), getName());
	}

	public static String buildSqlDropIndexString(Dialect dialect, TableMetaData tbmd, String name, String defaultCatalog, String defaultSchema) {
		return "DROP INDEX " + StringHelper.qualify(tbmd.getQualifiedName(dialect, defaultCatalog, defaultSchema), name);
	}

	public String sqlConstraintString(Dialect dialect) {
		StringBuffer buf = new StringBuffer(" INDEX (");
		Iterator<FieldMetaData> iter = getColumnIterator();
		while (iter.hasNext()) {
			buf.append(((FieldMetaData) iter.next()).getQuotedName(dialect));
			if (iter.hasNext())
				buf.append(", ");
		}
		return buf.append(')').toString();
	}

	// -----  -----------------------------------------------------------------
	
	public TableMetaData getTableMetaData() {
		return tbmd;
	}

	public void setTableMetaData(TableMetaData tbmd) {
		this.tbmd = tbmd;
	}

	public int getColumnSpan() {
		return columns.size();
	}

	public Iterator<FieldMetaData> getColumnIterator() {
		return columns.iterator();
	}

	public void addColumn(FieldMetaData column) {
		if (!columns.contains(column))
			columns.add(column);
	}

	public void addColumns(Iterator<FieldMetaData> extraColumns) {
		while (extraColumns.hasNext()) {
			addColumn((FieldMetaData) extraColumns.next());
		}
	}

	/**
	 * @param column
	 * @return true if this constraint already contains a column with same name.
	 */
	public boolean containsColumn(FieldMetaData fmd) {
		return columns.contains(fmd);
	}

	// -----  -----------------------------------------------------------------
	
	/**
	 * @return the type
	 */
	public String getType() {
		return type;
	}

	/**
	 * @param type the type to set
	 */
	public void setType(String type) {
		this.type = type;
	}

	/**
	 * @return the unique
	 */
	public boolean isUnique() {
		return unique;
	}

	/**
	 * @param unique the unique to set
	 */
	public void setUnique(boolean unique) {
		this.unique = unique;
	}

	// ----- -----------------------------------------------------------------

	/* (non-Javadoc)
	 * @see com.smart4web.db.structure.MetaData#toString()
	 */
	public String toString() {
		return getClass().getName() + "(" + getName() + ")";
	}

	// ----- -----------------------------------------------------------------

	/**
	 * Funkce p�etransformuje objekt typu IndexMetaData do XML.
	 * 
	 * @return String - n�vratov� hodnota je �et�zec XML
	 * @throws Exception the exception
	 * @param
	 */
	public String transToXML() throws Exception {
		DOMElement node = new DOMElement("IDXMD");
		return transToXML(node).asXML();
	}

	/**
	 * Funkce p�etransformuje objekt typu IndexMetaData do objekt typu DOMElement
	 * 
	 * @param DOMElement
	 *            node
	 * @return DOMElement
	 */
	public DOMElement transToXML(DOMElement node) throws Exception {
		node.setName("IDXMD");
		return node;
	}

	// ----- -----------------------------------------------------------------

	/**
	 * Funkce p�etransformuje �et�zec XML na objekt typu MetaData
	 * 
	 * @param String
	 *            xml
	 * @return IndexMetaData
	 */
	public IndexMetaData xmlToExpr(String xml) throws Exception {
		return this;
	}

	/**
	 * Funkce p�etransformuje objekt typu org.dom4j.Element na objekt typu
	 * MetaData
	 * 
	 * @param Element node
	 * @return IndexMetaData
	 */
	public IndexMetaData xmlToExpr(Element node) throws Exception {
		if (node.getName().equals("PKMD")) {
			// this.setTableMetaData(node.attributeValue("table"));
			// this.setPkName(node.attributeValue("pkname"));
			// this.setColumn(node.attributeValue("column"));
		}
		return this;
	}
}
